package com.hyy.lotterysystem.controller.handler;
import com.hyy.lotterysystem.common.errorcode.GlobalErrorCodeConstants;
import com.hyy.lotterysystem.common.exception.ControllerException;
import com.hyy.lotterysystem.common.exception.ServiceException;
import com.hyy.lotterysystem.common.pojo.CommonResult;
import org.apache.ibatis.exceptions.PersistenceException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

@RestControllerAdvice //全局捕获异常
public class GlobalExceptionHandler {

    //指定日志打印的类
    private final static Logger logger= LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(ServiceException.class)
    public CommonResult<?> serviceException(ServiceException e) {
        //打印错误日志
        logger.error("serviceException: "+e.getMessage());

        //构造错误返回结果
        return CommonResult.error(
                GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),
                e.getMessage()
        );
    }

    @ExceptionHandler(ControllerException.class)
    public CommonResult<?> controllerException(ControllerException e) {
        //打印错误日志
        logger.error("controllerException: "+e.getMessage());

        //构造错误返回结果
        return CommonResult.error(
                GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR.getCode(),//返回的500
                e.getMessage()
        );
    }

    /**
     * 处理参数校验异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public CommonResult<?> handleValidationExceptions(MethodArgumentNotValidException ex) {
        BindingResult bindingResult = ex.getBindingResult();
        Map<String, String> errors = new HashMap<>();
        
        for (FieldError fieldError : bindingResult.getFieldErrors()) {
            errors.put(fieldError.getField(), fieldError.getDefaultMessage());
        }
        
        // 记录日志
        logger.error("参数校验失败: {}", errors);
        
        // 取第一个错误消息作为主要错误信息
        String errorMessage = bindingResult.getFieldErrors().get(0).getDefaultMessage();
        
        return CommonResult.error(
                GlobalErrorCodeConstants.PARAM_ERROR.getCode(),
                errorMessage
        );
    }

    //捕获其余未知异常
    @ExceptionHandler(Exception.class)
    public CommonResult<?> exception(Exception e) {
        //打印错误日志
        logger.error("服务器未知异常Exception: {}", e.getMessage(), e);
        //构造错误返回结果
        return CommonResult.error(
                GlobalErrorCodeConstants.UNKNOWN.getCode(),//返回的999
                e.getMessage()!=null?e.getMessage():"服务器异常"
        );
    }

    @ExceptionHandler(PersistenceException.class)
    public CommonResult<?> handleMyBatisException(PersistenceException e) {
        logger.error("MyBatis异常: ", e);

        // 获取根本原因（通常是SQLException）
        Throwable cause = e.getCause();
        String errorMsg = "数据库操作失败";

        if (cause instanceof SQLException) {
            SQLException sqlEx = (SQLException) cause;
            // 可以根据SQL错误码进行更详细的处理
            int errorCode = sqlEx.getErrorCode();

            if (errorCode == 1062) {  // MySQL唯一键冲突
                errorMsg = "数据已存在，请勿重复添加";
            } else if (errorCode == 1451) {  // 外键约束
                errorMsg = "数据被引用，无法删除";
            }
        }

        return CommonResult.error(
                GlobalErrorCodeConstants.UNKNOWN.getCode(),
                errorMsg
        );
    }

}
